<template>
    <div>
        <el-col :span="40">
            <el-card shadow="hover">
                <div class="card-header">
                    <p class="card-header-title">北京市交通事故分布图</p>
                </div>
                <v-chart v-if="init_map_show" class="map-chart" ref="mapRef" :loading :option="mapOption" />
                <v-chart v-if="graph_show" class="map-chart" ref="graphRef" :loading="graphLoading" :option="graphOption" />
            </el-card>
        </el-col>
    </div>
</template>

<script setup lang="ts">
import VChart from 'vue-echarts';
import { onMounted, ref } from 'vue';
import { use, registerMap } from "echarts/core";
import { ScatterChart, MapChart, GraphChart } from "echarts/charts"
import { CanvasRenderer } from "echarts/renderers";
import {
    TooltipComponent,
    VisualMapComponent,
    ToolboxComponent,
    GeoComponent
} from "echarts/components";
import * as beijingMap from '@/utils/maps/beijing';
import { mapOption, areaMapOption, graphOption } from './options';
import { ECharts } from 'echarts';
import { getAccidentGraph, getAccidents, getAreaAccidents } from '@/api';
import { getRandomInt } from '@/utils';
import { AccidentGraph, GraphNode, graphNode } from '@/types/graph';

use([
    CanvasRenderer,
    TooltipComponent,
    VisualMapComponent,
    ToolboxComponent,
    GeoComponent,
    ScatterChart,
    MapChart,
    GraphChart
]);

const mapRef = ref<ECharts | null>(null);
const init_map_show = ref(true);

const graphRef = ref<ECharts | null>(null)
const graph_show = ref(false);

const loading = ref(true);
const graphLoading = ref(false);

// 记录点击的区名
let areaName: string = '东城区';

// 初始化北京市地图
registerMap('beijing', beijingMap.beijing);
// 初始渲染区地图(先初始化，后动态渲染)
registerMap('dongcheng', beijingMap['dongcheng']);

onMounted(() => {
    initData();
});

async function initData() {
    // 加载效果开启
    loading.value = true;
    registerMap('beijing', beijingMap.beijing); 
    mapOption.geo.map = 'beijing';
    mapOption.visualMap = {
        show: true,
        realtime: false,
        calculable: false,
    }
    mapOption.series[0].map = 'beijing';
    mapOption.tooltip = {
        triggerOn: 'click',
        formatter: (params) => {
            changeMap(params.name);
        }
    }
    
    const res = await getAccidents();
    if (res.data != null && res.data.length > 0) {
        res.data.forEach((item) => {
            // 设置数据;
            mapOption.series[0].data.push({name: item.district, value: item.count});
        })
    }

    mapRef.value.setOption(mapOption);
    
    loading.value = false; // 数据加载完毕，隐藏加载提示
}

async function changeMap(name: string) {
    // 记录当前切换的哪个区的地图
    areaName = name;
    // 加载效果
    loading.value = true;
    // 获取区域地图名称
    let mapName = getMapName(name);
    // 渲染地图
    registerMap(mapName, beijingMap[mapName]);
    // 地图option
    areaMapOption.geo.map = mapName;
    areaMapOption.geo.map = mapName;
    areaMapOption.toolbox = {
        show: true,
        feature: {
            myTool1: {
                show: true,
                title: "返回",
                icon: "path://M512 64L64 512l448 448 192-192L448 512l256-256z",
                onclick: function () {
                    initData();
                },
            }
        }
    };
    areaMapOption.tooltip = {
        trigger: 'item',
        triggerOn: 'click',
        formatter: (params) => {
            showGraph(params.name);
        }
    };

    // 获取数据
    const res = await getAreaAccidents(name);
    if (res.data != null && res.data.length > 0) {
        res.data.forEach(item => {
            areaMapOption.series[0].data.push({ name: item.accidentId, value: [item.lat, item.lng, 10000]})
        });
    }
    // 设置option
    mapRef.value.setOption(areaMapOption);
    // 显示
    loading.value = false;
}

function getMapName(name: string) {
    switch(name) {
        case '朝阳区': return 'chaoyang'
        case '西城区': return 'xicheng'
        case '东城区': return 'dongcheng'
        case '海淀区': return 'haidian'
        case '丰台区': return 'fengtai'
        case '大兴区': return 'daxing'
        case '通州区': return 'tongzhou'
        case '房山区': return 'fangshan'
        case '石景山区': return 'shijingshan'
        case '门头沟区': return 'mentougou'
        case '昌平区': return 'changping'
        case '顺义区': return 'shunyi'
        case '平谷区': return 'pinggu'
        case '密云区': return 'miyun'
        case '怀柔区': return 'huairou'
        case '延庆区': return 'yanqing'
    }
}

async function showGraph(name: string) {
    init_map_show.value = false;
    graph_show.value = true;

    graphLoading.value = true;

    graphOption.toolbox = {
        show: true,
        feature: {
            myTool2: {
                show: true,
                title: "返回",
                icon: "path://M512 64L64 512l448 448 192-192L448 512l256-256z",
                onclick: function () {
                    graph_show.value = false;
                    init_map_show.value = true;
                    // 回退，切换到区图
                    changeMap(areaName);
                },
            }
        }
    };
    
    // 获取数据 name 是 事故id
    const res = await getAccidentGraph(name);
    const data: AccidentGraph = res.data;
    // 先将option里的data清空
    graphOption.series[0].data = [];
    graphOption.series[0].links = [];
    if (data != null) {
        if (data.nodes.length > 0) {
            const nodes: GraphNode[] = data.nodes;
            nodes.forEach(item => {
                graphOption.series[0].data.push({ name: item.name, x: getRandomInt(100, 600), y: getRandomInt(100, 600) })
            });
            if (data.relations.length > 0) {
                data.relations.forEach(item => {
                    let source = '',target = '';
                    for (let i = 0; i < nodes.length; i++) {
                        if (nodes[i].id === item.from) {
                            source = nodes[i].name;
                        }
                        if (nodes[i].id === item.to) {
                            target = nodes[i].name;
                        }
                    }
                    graphOption.series[0].links.push({
                        source: source,
                        target: target,
                        label: {
                            show: true,
                            formatter: item.name
                        }
                    })
                });
            }
        }
    }

    graphRef.value.setOption(graphOption);

    graphLoading.value = false;
}

</script>

<style scoped>
.map-chart {
    width: 100%;
    height: 700px;
}
</style>